package com.easy.lab.shixun.service.manager;

import com.easy.lab.shixun.common.annotation.SxEventProcessor;
import com.easy.lab.shixun.common.enums.MessageTypeEnums;
import com.easy.lab.shixun.service.processor.BaseEventProcessor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 通过SxEventProcessor注解获取所有事件处理器，并注册
 * @Author: https://gitee.com/wesleyOne
 * @Date: 12.12 2019
 */
@Component
@Slf4j
public final class EventProcessorManager implements ApplicationContextAware {

    private static final Map<String, BaseEventProcessor> PROCESSOR_MAP = new ConcurrentHashMap<>(16);

    @Override
    public void setApplicationContext(ApplicationContext ctx) throws BeansException {
        Map<String, Object> processors = ctx.getBeansWithAnnotation(SxEventProcessor.class);
        if (CollectionUtils.isNotEmpty(processors.values())) {
            for (Object confBean : processors.values()) {
                Class<?> clz = confBean.getClass();
                // 解决CGLIB代理问题(借鉴elastic-job-spring-boot-starter项目处理)
                String interfaceName = clz.getInterfaces()[0].getSimpleName();
                if (!"BaseEventProcessor".contains(interfaceName)) {
                    clz = clz.getSuperclass();
                }
                SxEventProcessor annotation = AnnotationUtils.findAnnotation(clz, SxEventProcessor.class);
                MessageTypeEnums messageType = annotation.messageType();
                PROCESSOR_MAP.put(messageType.name(), (BaseEventProcessor)confBean);
                log.debug("事件处理器添加成功 {} - {}",messageType.getName(), clz.getSimpleName());
            }
        }
    }

    public Map<String, BaseEventProcessor> getProcessorMap() {
        return PROCESSOR_MAP;
    }
}
